package com.r2r.fetus;

import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * @author du
 * 通讯规约V1,目前适用12.1寸胎儿监护仪  与V3不同点在于：(1)、每一种数据前都跟完整包头02000401020004050c0004041112131415060708090a   (2)、包长不包含类型码和床号的长度。
 * 3号机数据。
 * 数据格式为：包头+包长（2位）+床号+类型码+数据。  包长
 * 例1：包长为0x40的数据            病人信息包，类型0x03
 * 02000401020004050c0004041112131415060708090a4000040300000000000000000000000000000000000000000000000001080009020600000000000000000000000000000000000000000000000000000000000000000000
 * 例2：包长为0x01的数据            病人信息包，类型0x0a
 * 02000401020004050c0004041112131415060708090a0100040a00
 * 
 * 
 * 
 * 例外：!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  考虑数据异常。需要确认。
 * 包长+类型码  字节为：2c04000f
 * 按规约解析，数据长度字节取值为  2c04
 * 分析实际是0f类型胎心数据，数据长度为2c,但发送过来实际数据长度为43，按这个长度解析出的胎心数据不正常，需要确认。
 * 
 * 
 * 02000401020004050c0004041112131415060708090a2c04000f5555555500050000920091009100910077007800780077000800080001003600390037003800000000000002000401020004050c0004041112131415060708090a400004030000000000000000000000000000000000000000000000000108000902060000000000000000000000000000000000000000000000000000000000000000000002000401020004050c0004041112131415060708090a0100040a0002000401020004050c0004041112131415060708090a2c04000f555555550005000091009000900090007700770077007800080008000100380039003b003c00000000000002000401020004050c0004041112131415060708090a400004030000000000000000000000000000000000000000000000000108000902060000000000000000000000000000000000000000000000000000000000000000000002000401020004050c0004041112131415060708090a0100040a0002000401020004050c0004041112131415060708090a2c04000f5555555500050000900090009000900078007800780077000800080001003c003b003a003a00000000000002000401020004050c0004041112131415060708090a40000403000000000000000000000000000000000000000000000000010800090206000000000000000000000000000000000000000000000000000002000401020004050c0004041112131415060708090a400004030000000000000000000000000000000000000000000000000108000902060000000000000000000000000000000000000000000000000000000000000000000002000401020004050c0004041112131415060708090a0100040a0002000401020004050c0004041112131415060708090a2c04000f55555555000500008d008d008d008c007d007d007d007d000800080001001c001d00200021000000000000
 * 000500008d008d008d008d007f007e007e007f00080008000100180019001a001b000000000000
 *
 * 
 * 
 */
public class FetusPacketV1 extends FetusPacket {
	private int dataLength;
	//通讯规约版本号
	private String protocolVersion="V1";
	/**
	 * 
	 */
	private static final long serialVersionUID = -2787527512107116434L;
	public static final byte[] header = new byte[]{0x02, 0x00, 0x04, 0x01, 0x02, 0x00, 0x04, 0x05, 0x0c, 0x00, 0x04, 0x04, 0x11, 0x12, 0x13, 0x14, 0x15, 0x06, 0x07, 0x08, 0x09, 0x0a};
//	public static final byte[] header1 = new byte[]{0x04, 0x0e, 0x01, 0x00, 0x01, 0x00, 0x18, (byte) 0xfc, (byte) 0x86, 0x01, 0x54, 0x01, 0x02, 0x00, 0x18, (byte) 0xfc, 0x7c, 0x01, 0x68, 0x01, 0x02, 0x00};
	public static final short[] lengths= new short[]{(short)0x0001,(short)0x02ac, (short)0x006a, (short)0x0028,(short)0x0014,(short)0x0040, (short)0x002c};
	

	public FetusPacketV1() {
		super();
		// TODO Auto-generated constructor stub
	}

	public FetusPacketV1(byte bedNo, byte type, byte[] body) {
		super();
		this.setBedNo(bedNo);
		this.setType(type);
		this.setBody(body);
		// TODO Auto-generated constructor stub
	}
	/**
	 * 查包头判断版本，    按定义的固定包头查找
	 * @param buffer
	 * @param readableLength
	 * @return
	 */
	public static boolean checkHeader(ByteBuffer buffer,int readableLength){
		boolean isV1=false;
//		System.out.println("V1Buffer:"+Util.bytesToHexString(buffer.array()));
//		String bfStr=Util.bytesToHexString(buffer.array());
//		String headerStr=Util.bytesToHexString(header);
		int headerLen=header.length;
		byte[] readHead = new byte[headerLen];
		int position = buffer.position();
		//找到固定包头位置，找到就定位到。
		int idx=Util.indexOfBytes(buffer, header);
		//找不到包头，返回false;
		if(idx<0)
			return false;
		//找到包头，将buffer定位到包头位置

		//读取包头
		buffer.get(readHead, 0, headerLen);
		int readLen=headerLen+idx;
		if(Arrays.equals(readHead,header)) {
			//获取数据长度
			short packetLen=buffer.getShort();
//			System.out.println("包长度："+packetLen);
			for(int j=0;j<lengths.length;j++) {
				if(lengths[j] == packetLen) {
					int bedNo =(short) (buffer.get() & 0xff);
					int type = buffer.get();		
					if(type<=0 || bedNo<0) {
						System.out.println("找到包头：bedNo或type错误:"+bedNo+"-"+type);
						buffer.position(position);
						return false;
					}
					buffer.position(position);
					return true;
				}
			}
			
		}
		buffer.position(position);
		return isV1;
	}
	/**
	 * 查包头判断版本，    按定义的   固定包头+数据长度     查找
	 * @param buffer
	 * @param readableLength
	 * @return
	 */
	public static boolean checkHeaderWithLength(ByteBuffer buffer,int readableLength){
		boolean isV1=false;
//		System.out.println("V1Buffer:"+Util.bytesToHexString(buffer.array()));
//		String bfStr=Util.bytesToHexString(buffer.array());
//		String headerStr=Util.bytesToHexString(header);
		int headerLen=header.length;
		int newLength=headerLen+2;
		byte[] readHead = new byte[headerLen];
		byte[] readHeadNew=Arrays.copyOf(header, newLength);
		int position = buffer.position();
		//找到固定包头位置，找到就定位到。
		int idx=Util.indexOfBytes(buffer, header);
		//找不到包头，返回false;
		if(idx<0)
			return false;
		//读取包头
		buffer.get(readHead, 0, headerLen);
		int readLen=headerLen+idx;
		if(Arrays.equals(readHead,header)) {
			//获取数据长度
			short packetLen=buffer.getShort();
			for(int j=0;j<lengths.length;j++) {
				if(lengths[j] == packetLen) {
					int bedNo = buffer.get();
					int type = buffer.get();		
					buffer.position(position);
					return true;
				}
			}
			//查找  header+length  
			int firstPos=-1;
			for(int j=0;j<lengths.length;j++) {
				short len=lengths[j];
				byte[] lenByte=Util.shortToBytes(len);
				readHeadNew[headerLen]=lenByte[1];
				readHeadNew[headerLen+1]=lenByte[0];
				int lenPos=Util.indexOfBytes(buffer, readHeadNew);
				if(lenPos>=0){
					if(firstPos>=0){
						if(lenPos<firstPos)
							firstPos=lenPos;
					}else{
						firstPos=lenPos;
					}
				}
				buffer.position(position);
			}
			if(firstPos>=0){
				buffer.position(firstPos);
				return true;
			}else{
				buffer.position(position);
				return false;
			}
		}
		
		return isV1;
	}
	public static FetusPacket parseFetusPacket(ByteBuffer buffer,int readableLength){
		FetusPacketV1 fetus=null;
		//System.out.println("    Length:"+readableLength+"解码V1Buffer:"+Util.bytesToHexString(buffer.array()));
		int neededLength=0;
		int headIdx=0;
		byte[] head=new byte[header.length];
		int position = buffer.position();
		//System.out.println("位置    position:"+position);
		//找到固定包头位置
		headIdx=Util.indexOfBytes(buffer, header);
		
		if(headIdx<0)
			return null;
//		System.out.println("    position:"+position+"  headerPos:"+headIdx);
		buffer.get(head,0,head.length);
		neededLength=buffer.getShort();
		//床位号
		short bedNo =Util.byteToShort( buffer.get());
		
		//消息类型
		byte type = buffer.get();
		//处理数据异常。类型为0x0f时 ，数据长度只有一位。
		if(type==0x0f ){
			if(bedNo==0){
			buffer.position(buffer.position()-4);
			// System.out.println(" 0f类型数据   position:"+buffer.position());
			neededLength=(short)buffer.get();
//			neededLength--;
			bedNo=buffer.get();
			buffer.get();
			type=buffer.get();
			}
		}
		if(type<=0 || bedNo<0) {
			System.out.println("V1***********找到包头：bedNo或type错误:"+bedNo+"-"+type);
			return null;
		}
		int readableLen = buffer.limit()-buffer.position();
		if(readableLen<neededLength) {//
			//System.out.println("V1***********不够消息体长度(剩下的buffe组不了消息体)-需要长度="+neededLength+"实际长度="+readableLen);
			return null;
		}
		fetus=new FetusPacketV1();
		fetus.setBedNo((byte)bedNo);
		fetus.setType(type);
		byte[] dst =new byte[neededLength];
		buffer.get(dst);
		fetus.setBody(dst);
		
		//System.out.println("V1*******************解析成功：LENGTH:"+dst.length+"-TYPE:"+Integer.toHexString(type));
		
		return fetus;
	}

	@Override
	public int getDataLength() {
		// TODO Auto-generated method stub
		return dataLength;
	}

	@Override
	public String getProtocolVersion() {
		// TODO Auto-generated method stub
		return protocolVersion;
	}

	@Override
	public int getHeaderLength() {
		// TODO Auto-generated method stub
		return header.length;
	}

	@Override
	public byte[] getHeader() {
		// TODO Auto-generated method stub
		return header;
	}
	
}
